<!doctype html>
<meta charset="utf8">

<emu-clause id="sec-temporal-abstract-ops">
  <h1>Abstract operations</h1>

  <!-- Based on ECMA-262 IterableToList -->
  <emu-clause id="sec-iterabletolistoftype" aoid="IterableToListOfType">
    <h1>IterableToListOfType ( _items_, _elementTypes_ )</h1>
    <p>
      The abstract operation IterableToListOfType takes arguments _items_ and _elementTypes_ (a List of names of ECMAScript Language Types).
      It is used to create a List value whose elements are provided by the values of the iterable _items_.
      _elementTypes_ contains the names of ECMAScript Language Types that are allowed for element values of the List that is created.
      It performs the following steps when called:
    </p>
    <emu-alg>
      1. Let _iteratorRecord_ be ? GetIterator(_items_, ~sync~).
      1. Let _values_ be a new empty List.
      1. Let _next_ be *true*.
      1. Repeat, while _next_ is not *false*,
        1. Set _next_ to ? IteratorStep(_iteratorRecord_).
        1. If _next_ is not *false*, then
          1. Let _nextValue_ be ? IteratorValue(_next_).
          1. If Type(_nextValue_) is not an element of _elementTypes_, then
            1. Let _completion_ be ThrowCompletion(a newly created *TypeError* object).
            1. Return ? IteratorClose(_iteratorRecord_, _completion_).
          1. Append _nextValue_ to the end of the List _values_.
      1. Return _values_.
    </emu-alg>
  </emu-clause>

  <!-- Copied from ECMA-402 GetOptionsObject -->
  <emu-clause id="sec-getoptionsobject" aoid="GetOptionsObject">
    <h1>GetOptionsObject ( _options_ )</h1>
    <p>
      The abstract operation GetOptionsObject returns an Object suitable for use with GetOption, either _options_ itself or a default empty Object.
      It throws a TypeError if _options_ is not undefined and not an Object.
    </p>
    <emu-alg>
      1. If _options_ is *undefined*, then
        1. Return ! OrdinaryObjectCreate(*null*).
      1. If Type(_options_) is Object, then
        1. Return _options_.
      1. Throw a *TypeError* exception.
    </emu-alg>
  </emu-clause>

  <!-- Based on ECMA-402 GetOption -->
  <emu-clause id="sec-getoption" aoid="GetOption">
    <h1>GetOption ( _options_, _property_, _types_, _values_, _fallback_ )</h1>

    <p>
      The abstract operation GetOption extracts the value of the property named _property_ from the provided _options_ object, checks whether its type is one of a List of allowed _types_ and converts it to the last one if not, checks whether it is one of a List of allowed _values_, and fills in a _fallback_ value if necessary. If _values_ is ~empty~, there is no fixed set of values and any is permitted.
    </p>

    <emu-alg>
      1. Assert: Type(_options_) is Object.
      1. Assert: Each element of _types_ is Boolean, String, or Number.
      1. Let _value_ be ? Get(_options_, _property_).
      1. If _value_ is *undefined*, return _fallback_.
      1. If _types_ contains Type(_value_), then
        1. Let _type_ be Type(_value_).
      1. Else,
        1. Let _type_ be the last element of _types_.
      1. If _type_ is Boolean, then
        1. Set _value_ to ! ToBoolean(_value_).
      1. Else if _type_ is Number, then
        1. Set _value_ to ? ToNumber(_value_).
        1. If _value_ is *NaN*, throw a *RangeError* exception.
      1. Else,
        1. Set _value_ to ? ToString(_value_).
      1. If _values_ is not ~empty~, then
        1. If _values_ does not contain _value_, throw a *RangeError* exception.
      1. Return _value_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-getstringornumberoption" aoid="GetStringOrNumberOption">
    <h1>GetStringOrNumberOption ( _options_, _property_, _stringValues_, _minimum_, _maximum_, _fallback_ )</h1>
    <p>
      The abstract operation GetStringOrNumberOption extracts the value of the property named _property_ from the provided _options_ object.
      If the value is a Number value, the operation checks whether it is in the allowed range.
      Otherwise, the operation converts it to a string and checks whether it is one of a List of allowed _stringValues_, and fills in a _fallback_ value if necessary.
    </p>
    <emu-alg>
      1. Assert: Type(_options_) is Object.
      1. Let _value_ be ? GetOption(_options_, _property_, « Number, String », ~empty~, _fallback_).
      1. If Type(_value_) is Number, then
        1. If _value_ &lt; _minimum_ or _value_ &gt; _maximum_, throw a *RangeError* exception.
        1. Return floor(ℝ(_value_)).
      1. Assert: Type(_value_) is String.
      1. If _stringValues_ does not contain _value_, throw a *RangeError* exception.
      1. Return _value_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-durationhandlefractions" aoid="DurationHandleFractions">
    <h1>DurationHandleFractions ( _fHours_, _minutes_, _fMinutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ )</h1>
    <emu-alg>
      1. If _fHours_ is not equal to 0, then
        1. If any of _minutes_, _fMinutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ is not 0, throw a *RangeError* exception.
        1. Let _mins_ be _fHours_ × 60.
        1. Set _minutes_ to floor(_mins_).
        1. Set _fMinutes_ to _mins_ modulo 1.
      1. If _fMinutes_ is not equal to 0, then
        1. If any of _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ is not 0, throw a *RangeError* exception.
        1. Let _secs_ be _fMinutes_ × 60.
        1. Set _seconds_ to floor(_secs_).
        1. Let _fSeconds_ be _secs_ modulo 1.
        1. If _fSeconds_ is not equal to 0, then
          1. If any of _milliseconds_, _microseconds_, _nanoseconds_ is not 0, throw a *RangeError* exception.
          1. Let _mils_ be _fSeconds_ × 1000.
          1. Set _milliseconds_ to floor(_mils_).
          1. Let _fMilliseconds_ be _mils_ modulo 1.
          1. If _fMilliseconds_ is not equal to 0, then
            1. If either _microseconds_ or _nanoseconds_ is not 0, throw a *RangeError* exception.
            1. Let _mics_ be _fMilliseconds_ × 1000.
            1. Set _microseconds_ to floor(_mics_).
            1. Let _fMicroseconds_ be _mils_ modulo 1.
            1. If _fMicroseconds_ is not equal to 0, then
              1. If _nanoseconds_ is not 0, throw a *RangeError* exception.
              1. Let _nans_ be _fMicroseconds_ × 1000.
              1. Set _nanoseconds_ to floor(_nans_).
      1. Return {
        [[Minutes]]: _minutes_,
        [[Seconds]]: _seconds_,
        [[Milliseconds]]: _milliseconds_,
        [[Microseconds]]: _microseconds_,
        [[Nanoseconds]]: _nanoseconds_
      }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporaloverflow" aoid="ToTemporalOverflow">
    <h1>ToTemporalOverflow ( _normalizedOptions_ )</h1>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporaldisambiguation" aoid="ToTemporalDisambiguation">
    <h1>ToTemporalDisambiguation ( _normalizedOptions_ )</h1>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporalroundingmode" aoid="ToTemporalRoundingMode">
    <h1>ToTemporalRoundingMode ( _normalizedOptions_, _fallback_ )</h1>
    <p>
      The abstract operation ToTemporalRoundingMode extracts the value of the property named *"roundingMode"* from _normalizedOptions_ and makes sure it is a valid value for the option.
      The value _fallback_ is returned if the property is not present.
    </p>
    <emu-note type="editor">
      <p>
        The rounding modes accepted by this abstract operation (and therefore in the Temporal API) are intended to be the same as whatever is eventually standardized in the <a href="https://github.com/tc39/proposal-intl-numberformat-v3">Intl.NumberFormat V3</a> proposal.
      </p>
    </emu-note>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"roundingMode"*, « String », « *"ceil"*, *"floor"*, *"trunc"*, *"halfExpand"* », _fallback_).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-negatetemporalroundingmode" aoid="NegateTemporalRoundingMode">
    <h1>NegateTemporalRoundingMode ( _roundingMode_ )</h1>
    <p>
      The abstract operation NegateTemporalRoundingMode returns the correct rounding mode to use when rounding the negative of a value that was originally given with _roundingMode_.
    </p>
    <emu-note type="editor">
      <p>
        The rounding modes accepted by this abstract operation (and therefore in the Temporal API) are intended to be the same as whatever is eventually standardized in the <a href="https://github.com/tc39/proposal-intl-numberformat-v3">Intl.NumberFormat V3</a> proposal.
      </p>
    </emu-note>
    <emu-alg>
      1. If _roundingMode_ is *"ceil"*, return *"floor"*.
      1. If _roundingMode_ is *"floor"*, return *"ceil"*.
      1. Return _roundingMode_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporaloffset" aoid="ToTemporalOffset">
    <h1>ToTemporalOffset ( _normalizedOptions_, _fallback_ )</h1>
    <p>
      The abstract operation ToTemporalOffset extracts the value of the property named *"offset"* from _normalizedOptions_ and makes sure it is a valid value for the option.
      The value _fallback_ is returned if the property is not present.
    </p>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-toshowcalendaroption" aoid="ToShowCalendarOption">
    <h1>ToShowCalendarOption ( _normalizedOptions_ )</h1>
    <p>
      The abstract operation ToShowCalendarOption extracts the value of the property named *"calendarName"* from _normalizedOptions_ and makes sure it is a valid value for the option.
    </p>
    <emu-note>
      This property is used in `toString` methods in Temporal to control whether a calendar annotation should be output.
    </emu-note>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-toshowtimezonenameoption" aoid="ToShowTimeZoneNameOption">
    <h1>ToShowTimeZoneNameOption ( _normalizedOptions_ )</h1>
    <p>
      The abstract operation ToShowTimeZoneNameOption extracts the value of the property named *"timeZoneName"* from _normalizedOptions_ and makes sure it is a valid value for the option.
    </p>
    <emu-note>
      This property is used in `Temporal.ZonedDateTime.prototype.toString()`.
      It is different from the `timeZone` property passed to `Temporal.ZonedDateTime.from()` and from the `timeZone` property in the options passed to `Temporal.Instant.prototype.toString()`.
    </emu-note>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-toshowoffsetoption" aoid="ToShowOffsetOption">
    <h1>ToShowOffsetOption ( _normalizedOptions_ )</h1>
    <p>
      The abstract operation ToShowOffsetOption extracts the value of the property named *"offset"* from _normalizedOptions_ and makes sure it is a valid value for the option.
    </p>
    <emu-note>
      This property is used in `Temporal.ZonedDateTime.prototype.toString()`.
      It is different from the `offset` property passed to `Temporal.ZonedDateTime.from()`.
    </emu-note>
    <emu-alg>
      1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporalroundingincrement" aoid="ToTemporalRoundingIncrement">
    <h1>ToTemporalRoundingIncrement ( _normalizedOptions_, _dividend_, _inclusive_ )</h1>
    <emu-alg>
      1. If _dividend_ is *undefined*, then
        1. Let _maximum_ be *+∞*.
      1. Else if _inclusive_ is *true*, then
        1. Let _maximum_ be _dividend_.
      1. Else if _dividend_ is more than 1, then
        1. Let _maximum_ be _dividend_ − 1.
      1. Else,
        1. Let _maximum_ be 1.
      1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », ~empty~, 1).
      1. If _increment_ &lt; 1 or _increment_ &gt; _maximum_, throw a *RangeError* exception.
      1. Set _increment_ to floor(ℝ(_increment_)).
      1. If _dividend_ is not *undefined* and _dividend_ modulo _increment_ is not zero, then
        1. Throw a *RangeError* exception.
      1. Return _increment_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporaldatetimeroundingincrement" aoid="ToTemporalDateTimeRoundingIncrement">
    <h1>ToTemporalDateTimeRoundingIncrement ( _normalizedOptions_, _smallestUnit_ )</h1>
    <p>
      The abstract operation ToTemporalDateTimeRoundingIncrement extracts the value of the property named *"roundingIncrement"* from _normalizedOptions_ and makes sure it is a valid value for the option, setting the correct maximum for rounding Temporal.ZonedDateTime and Temporal.PlainDateTime.
    </p>
    <emu-alg>
      1. If _smallestUnit_ is *"day"*, then
        1. Let _maximum_ be 1.
      1. Else if _smallestUnit_ is *"hour"*, then
        1. Let _maximum_ be 24.
      1. Else if _smallestUnit_ is *"minute"* or *"second"*, then
        1. Let _maximum_ be 60.
      1. Else,
        1. Assert: _smallestUnit_ is *"millisecond"*, *"microsecond"*, or *"nanosecond"*.
        1. Let _maximum_ be 1000.
      1. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-tosecondsstringprecision" aoid="ToSecondsStringPrecision">
    <h1>ToSecondsStringPrecision ( _normalizedOptions_ )</h1>
    <p>
      The abstract operation ToSecondsStringPrecision combines the values of the options `smallestUnit` and `fractionalSecondDigits` to yield a precision for printing minutes and seconds to a string, and a rounding unit and increment.
      The precision may be an integer 0 through 9 signifying a number of digits after the decimal point in the seconds, the string *"minute"* signifying not to print seconds at all, or the string *"auto"* signifying to drop trailing zeroes after the decimal point.
    </p>
    <emu-alg>
      1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_normalizedOptions_, « *"year"*, *"month"*, *"week"*, *"day"*, *"hour"* », *undefined*).
      1. If _smallestUnit_ is *"minute"*, then
        1. Return the new Record {
            [[Precision]]: *"minute"*,
            [[Unit]]: *"minute"*,
            [[Increment]]: 1
          }.
      1. If _smallestUnit_ is *"second"*, then
        1. Return the new Record {
            [[Precision]]: 0,
            [[Unit]]: *"second"*,
            [[Increment]]: 1
          }.
      1. If _smallestUnit_ is *"millisecond"*, then
        1. Return the new Record {
            [[Precision]]: 3,
            [[Unit]]: *"millisecond"*,
            [[Increment]]: 1
          }.
      1. If _smallestUnit_ is *"microsecond"*, then
        1. Return the new Record {
            [[Precision]]: 6,
            [[Unit]]: *"microsecond"*,
            [[Increment]]: 1
          }.
      1. If _smallestUnit_ is *"nanosecond"*, then
        1. Return the new Record {
            [[Precision]]: 9,
            [[Unit]]: *"nanosecond"*,
            [[Increment]]: 1
          }.
      1. Assert: _smallestUnit_ is *undefined*.
      1. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
      1. If _digits_ is *"auto"*, then
        1. Return the new Record {
            [[Precision]]: *"auto"*,
            [[Unit]]: *"nanosecond"*,
            [[Increment]]: 1
          }.
      1. If _digits_ is 0, then
        1. Return the new Record {
            [[Precision]]: 0,
            [[Unit]]: *"second"*,
            [[Increment]]: 1
          }.
      1. If _digits_ is 1, 2, or 3, then
        1. Return the new Record {
            [[Precision]]: _digits_,
            [[Unit]]: *"millisecond"*,
            [[Increment]]: 10<sup>3 − _digits_</sup>
          }.
      1. If _digits_ is 4, 5, or 6, then
        1. Return the new Record {
            [[Precision]]: _digits_,
            [[Unit]]: *"microsecond"*,
            [[Increment]]: 10<sup>6 − _digits_</sup>
          }.
      1. Assert: _digits_ is 7, 8, or 9.
      1. Return the new Record {
          [[Precision]]: _digits_,
          [[Unit]]: *"nanosecond"*,
          [[Increment]]: 10<sup>9 − _digits_</sup>
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-tolargesttemporalunit" aoid="ToLargestTemporalUnit">
    <h1>ToLargestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_ [ , _autoValue_ ] )</h1>
    <p>
      The abstract operation ToLargestTemporalUnit consults the `largestUnit` property of the Object _normalizedOptions_, and checks that it is a valid unit and not one of a List of _disallowedUnits_.
      It returns a _fallback_ value if the property is not present.
      Optionally, if an _autoValue_ is provided, then a value of *"auto"* is replaced with this value.
    </p>
    <p>
      Both singular and plural unit names are accepted, but only the singular form is returned.
    </p>
    <emu-alg>
      1. Assert: _disallowedUnits_ does not contain _fallback_.
      1. Assert: _disallowedUnits_ does not contain *"auto"*.
      1. Assert: _autoValue_ is not present or _fallback_ is *"auto"*.
      1. Assert: _autoValue_ is not present or _disallowedUnits_ does not contain _autoValue_.
      1. Let _largestUnit_ be ? GetOption(_normalizedOptions_, *"largestUnit"*, « String », « *"auto"*, *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
      1. If _largestUnit_ is *"auto"* and _autoValue_ is present, then
        1. Return _autoValue_.
      1. If _largestUnit_ is in the Plural column of <emu-xref href="#table-temporal-singular-and-plural-units"></emu-xref>, then
        1. Set _largestUnit_ to the corresponding Singular value of the same row.
      1. If _disallowedUnits_ contains _largestUnit_, then
        1. Throw a *RangeError* exception.
      1. Return _largestUnit_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-tosmallesttemporalunit" aoid="ToSmallestTemporalUnit">
    <h1>ToSmallestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_ )</h1>
    <p>
      The abstract operation ToSmallestTemporalUnit consults the `smallestUnit` property of the Object _normalizedOptions_, and checks that it is a valid unit and not one of a List of _disallowedUnits_.
      It returns a _fallback_ value if the property is not present.
    </p>
    <p>
      Both singular and plural unit names are accepted, but only the singular form is returned.
    </p>
    <emu-alg>
      1. Assert: _disallowedUnits_ does not contain _fallback_.
      1. Let _smallestUnit_ be ? GetOption(_normalizedOptions_, *"smallestUnit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
      1. If _smallestUnit_ is in the Plural column of <emu-xref href="#table-temporal-singular-and-plural-units"></emu-xref>, then
        1. Set _smallestUnit_ to the corresponding Singular value of the same row.
      1. If _disallowedUnits_ contains _smallestUnit_, then
        1. Throw a *RangeError* exception.
      1. Return _smallestUnit_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-totemporaldurationtotalunit" aoid="ToTemporalDurationTotalUnit">
    <h1>ToTemporalDurationTotalUnit ( _normalizedOptions_ )</h1>
    <p>
      The abstract operation ToTemporalDurationTotalUnit consults the `unit` property of the Object _normalizedOptions_, and checks that it is a valid unit.
      It returns *undefined* if the property is not present.
    </p>
    <p>
      Both singular and plural unit names are accepted, but only the singular form is returned.
    </p>
    <emu-alg>
      1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*).
      1. If _unit_ is *undefined*, then
        1. Throw a *RangeError* exception.
      1. If _unit_ is in the Plural column of <emu-xref href="#table-temporal-singular-and-plural-units"></emu-xref>, then
        1. Set _unit_ to the corresponding Singular value of the same row.
      1. Return _unit_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-singular-and-plural-units">
    <h1>Singular and plural units</h1>
    <p>
      Where possible, the `smallestUnit`, `largestUnit`, and `unit` options accept both singular and plural forms.
      Only the singular form is used internally.
    </p>
    <emu-table id="table-temporal-singular-and-plural-units">
      <emu-caption>Singular and plural units</emu-caption>
      <table class="real-table">
        <thead>
          <tr>
            <th>Singular</th>
            <th>Plural</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>*"year"*</td>
            <td>*"years"*</td>
          </tr>

          <tr>
            <td>*"month"*</td>
            <td>*"months"*</td>
          </tr>

          <tr>
            <td>*"week"*</td>
            <td>*"weeks"*</td>
          </tr>

          <tr>
            <td>*"day"*</td>
            <td>*"days"*</td>
          </tr>

          <tr>
            <td>*"hour"*</td>
            <td>*"hours"*</td>
          </tr>

          <tr>
            <td>*"minute"*</td>
            <td>*"minutes"*</td>
          </tr>

          <tr>
            <td>*"second"*</td>
            <td>*"seconds"*</td>
          </tr>

          <tr>
            <td>*"millisecond"*</td>
            <td>*"milliseconds"*</td>
          </tr>

          <tr>
            <td>*"microsecond"*</td>
            <td>*"microseconds"*</td>
          </tr>

          <tr>
            <td>*"nanosecond"*</td>
            <td>*"nanoseconds"*</td>
          </tr>
        </tbody>
      </table>
    </emu-table>
  </emu-clause>

  <emu-clause id="sec-temporal-torelativetemporalobject" aoid="ToRelativeTemporalObject">
    <h1>ToRelativeTemporalObject ( _options_ )</h1>
    <p>
      The abstract operation ToRelativeTemporalObject examines the value of the `relativeTo` property of its _options_ argument.
      If this is not present, it returns *undefined*.
      Otherwise, it attempts to return a Temporal.ZonedDateTime instance or Temporal.PlainDateTime instance, in order of preference, by converting the value.
      If neither of those are possible, the operation throws a *RangeError*.
    </p>
    <emu-alg>
      1. Assert: Type(_options_) is Object.
      1. Let _value_ be ? Get(_options_, *"relativeTo"*).
      1. If _value_ is *undefined*, then
        1. Return _value_.
      1. If Type(_value_) is Object, then
        1. If _value_ has either an [[InitializedTemporalDateTime]] or [[InitializedTemporalZonedDateTime]] internal slot, then
          1. Return _value_.
        1. If _value_ has an [[InitializedTemporalDate]] internal slot, then
          1. Return ? CreateTemporalDateTime(_value_.[[ISOYear]], _value_.[[ISOMonth]], _value_.[[ISODay]], 0, 0, 0, 0, 0, 0, _value_.[[Calendar]]).
        1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_value_).
        1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
        1. Let _fields_ be ? PrepareTemporalFields(_value_, _fieldNames_, «»).
        1. Let _dateOptions_ be ! OrdinaryObjectCreate(*null*).
        1. Perform ! CreateDataPropertyOrThrow(_dateOptions_, *"overflow"*, *"constrain"*).
        1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _dateOptions_).
        1. Let _offset_ be ? Get(_value_, *"offset"*).
        1. Let _timeZone_ be ? Get(_value_, *"timeZone"*).
      1. Else,
        1. Let _string_ be ? ToString(_value_).
        1. Let _result_ be ? ParseISODateTime(_string_).
        1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
        1. Let _offset_ be _result_.[[TimeZoneOffset]].
        1. Let _timeZone_ be _result_.[[TimeZoneIANAName]].
      1. If _timeZone_ is not *undefined*, then
        1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
        1. If _offset_ is not *undefined*, then
          1. Set _offset_ to ? ToString(_offset_).
          1. Let _offsetNs_ be ? ParseTimeZoneOffsetString(_offset_).
        1. Else,
          1. Let _offsetNs_ be *null*.
        1. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*).
        1. Return ? CreateTemporalZonedDateTime(_epochNanoseconds_, _timeZone_, _calendar_).
      1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-validatetemporalunitrange" aoid="ValidateTemporalUnitRange">
    <h1>ValidateTemporalUnitRange ( _largestUnit_, _smallestUnit_ )</h1>
    <emu-alg>
      1. If _smallestUnit_ is *"year"* and _largestUnit_ is not *"year"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"month"* and _largestUnit_ is not *"year"* or *"month"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"week"* and _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"day"* and _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"hour"* and _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, *"day"*, or *"hour"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"minute"* and _largestUnit_ is *"second"*, *"millisecond"*, *"microsecond"*, or *"nanosecond"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"second"* and _largestUnit_ is *"millisecond"*, *"microsecond"*, or *"nanosecond"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"millisecond"* and _largestUnit_ is *"microsecond"* or *"nanosecond"*, then
        1. Throw a *RangeError* exception.
      1. If _smallestUnit_ is *"microsecond"* and _largestUnit_ is *"nanosecond"*, then
        1. Throw a *RangeError* exception.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-largeroftwotemporalunits" aoid="LargerOfTwoTemporalUnits">
    <h1>LargerOfTwoTemporalUnits ( _u1_, _u2_ )</h1>
    <p>
      The abstract operation LargerOfTwoTemporalUnits, given two strings representing units of time, returns the string representing the larger of the two units.
    </p>
    <emu-alg>
      1. If either _u1_ or _u2_ is *"year"*, return *"year"*.
      1. If either _u1_ or _u2_ is *"month"*, return *"month"*.
      1. If either _u1_ or _u2_ is *"week"*, return *"week"*.
      1. If either _u1_ or _u2_ is *"day"*, return *"day"*.
      1. If either _u1_ or _u2_ is *"hour"*, return *"hour"*.
      1. If either _u1_ or _u2_ is *"minute"*, return *"minute"*.
      1. If either _u1_ or _u2_ is *"second"*, return *"second"*.
      1. If either _u1_ or _u2_ is *"millisecond"*, return *"millisecond"*.
      1. If either _u1_ or _u2_ is *"microsecond"*, return *"microsecond"*.
      1. Return *"nanosecond"*.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-mergelargestunitoption" aoid="MergeLargestUnitOption">
    <h1>MergeLargestUnitOption ( _options_, _largestUnit_ )</h1>
    <p>
      The abstract operation MergeLargestUnitOption returns a new plain Object with enumerable own String properties copied from the _options_ Object, and the `largestUnit` property set to _largestUnit_.
    </p>
    <emu-alg>
      1. Let _merged_ be ! OrdinaryObjectCreate(%Object.prototype%).
      1. Let _keys_ be ? EnumerableOwnPropertyNames(_options_, ~key~).
      1. For each element _nextKey_ of _keys_, do
        1. Let _propValue_ be ? Get(_options_, _nextKey_).
        1. Perform ! CreateDataPropertyOrThrow(_merged_, _nextKey_, _propValue_).
      1. Perform ! CreateDataPropertyOrThrow(_merged_, *"largestUnit"*, _largestUnit_).
      1. Return _merged_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-maximumtemporaldurationroundingincrement" aoid="MaximumTemporalDurationRoundingIncrement">
    <h1>MaximumTemporalDurationRoundingIncrement ( _unit_ )</h1>
    <emu-alg>
      1. If _unit_ is *"year"*, *"month"*, *"week"*, or *"day"*, then
        1. Return *undefined*.
      1. If _unit_ is *"hour"*, then
        1. Return 24.
      1. If _unit_ is *"minute"* or *"second"*, then
        1. Return 60.
      1. Assert: _unit_ is one of *"millisecond"*, *"microsecond"*, or *"nanosecond"*.
      1. Return 1000.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-rejecttemporalcalendartype" aoid="RejectTemporalCalendarType">
    <h1>RejectTemporalCalendarType ( _object_ )</h1>
    <p>
      The abstract operation RejectTemporalCalendarType throws an exception if its argument _object_ is an instance of one of the Temporal types that carries a calendar.
    </p>
    <emu-alg>
      1. Assert: Type(_object_) is Object.
      1. If _object_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
          1. Throw a *TypeError* exception.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-formatsecondsstringpart" aoid="FormatSecondsStringPart">
    <h1>FormatSecondsStringPart ( _second_, _millisecond_, _microsecond_, _nanosecond_, _precision_ )</h1>
    <emu-alg>
      1. Assert: _second_, _millisecond_, _microsecond_ and _nanosecond_ are integers.
      1. If _precision_ is *"minute"*, return *""*.
      1. Let _secondsString_ be the string-concatenation of the code unit 0x003A (COLON) and _second_ formatted as a two-digit decimal number, padded to the left with zeroes if necessary.
      1. Let _fraction_ be _millisecond_ × 10<sup>6</sup> + _microsecond_ × 10<sup>3</sup> + _nanosecond_.
      1. If _precision_ is *"auto"*, then
        1. If _fraction_ is 0, return _secondsString_.
        1. Set _fraction_ to _fraction_ formatted as a nine-digit decimal number, padded to the left with zeroes if necessary.
        1. Set _fraction_ to the longest possible substring of _fraction_ starting at position 0 and not ending with the code unit 0x0030 (DIGIT ZERO).
      1. Else,
        1. If _precision_ is 0, return _secondsString_.
        1. Set _fraction_ to _fraction_ formatted as a nine-digit decimal number, padded to the left with zeroes if necessary.
        1. Set _fraction_ to the substring of _fraction_ from 0 to _precision_.
      1. Return the string-concatenation of _secondsString_, the code unit 0x002E (FULL STOP), and _fraction_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-sign" aoid="Sign">
    <h1>Sign ( _n_ )</h1>
    <p>
      The abstract operation Sign takes argument _n_ and returns the mathematical sign of _n_.
    </p>
    <emu-note type="editor">
      This operation is the same as Math.sign and should be used there as well when merged into ECMA-262.
    </emu-note>
    <emu-alg>
      1. If _n_ is *NaN*, n is *+0*<sub>𝔽</sub>, or n is *−0*<sub>𝔽</sub>, return _n_.
      1. If _n_ &lt; *+0*<sub>𝔽</sub>, return *−1*<sub>𝔽</sub>.
      1. Return *1*<sub>𝔽</sub>.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-constraintorange" aoid="ConstrainToRange">
    <h1>ConstrainToRange ( _x_, _minimum_, _maximum_ )</h1>
    <emu-alg>
      1. Return min(max(_x_, _minimum_), _maximum_).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-roundtowardszero" aoid="RoundTowardsZero">
    <h1>RoundTowardsZero ( _x_ )</h1>
    <emu-alg>
      1. Return the mathematical value that is the same sign as _x_ and whose magnitude is floor(abs(_x_)).
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-roundhalfawayfromzero" aoid="RoundHalfAwayFromZero">
    <h1>RoundHalfAwayFromZero ( _x_ )</h1>
    <emu-alg>
      1. Return the mathematical value that is closest to _x_ and is an integer.
         If two integers are equally close to _x_, then the result is the integer that is farther away from 0. If _x_ is already an integer, then the result is _x_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-roundnumbertoincrement" aoid="RoundNumberToIncrement">
    <h1>RoundNumberToIncrement ( _x_, _increment_, _roundingMode_ )</h1>
    <p>
      The abstract operation RoundNumberToIncrement rounds the mathematical value _x_ to the nearest multiple of the integer _increment_.
      It rounds up or down according to _roundingMode_.
    </p>
    <emu-note type="editor">
      <p>
        The rounding modes accepted by this abstract operation are intended to be the same as whatever is eventually standardized in the <a href="https://github.com/tc39/proposal-intl-numberformat-v3">Intl.NumberFormat V3</a> proposal.
      </p>
    </emu-note>
    <emu-alg>
      1. Assert: _x_ and _increment_ are mathematical values.
      1. Assert: _roundingMode_ is *"ceil"*, *"floor"*, *"trunc"*, or *"halfExpand"*.
      1. Let _quotient_ be _x_ / _increment_.
      1. If _roundingMode_ is *"ceil"*, then
        1. Let _rounded_ be −floor(−_quotient_).
      1. Else if _roundingMode_ is *"floor"*, then
        1. Let _rounded_ be floor(_quotient_).
      1. Else if _roundingMode_ is *"trunc"*, then
        1. Let _rounded_ be the integral part of _quotient_, removing any fractional digits.
      1. Else,
        1. Let _rounded_ be ! RoundHalfAwayFromZero(_quotient_).
      1. Return _rounded_ × _increment_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-iso8601grammar">
    <h1>ISO 8601 grammar</h1>
    <p>
      Several operations in this section are intended to parse ISO 8601 strings representing a date, a time, a duration, or a combined date and time.
      For the purposes of these operations, a valid ISO 8601 string is defined as a string that can be generated by one of the goal elements of the following grammar.
    </p>
    <p>
      This grammar is adapted from the ABNF grammar of ISO 8601 that is given in section 5.8 of <a href="https://ryzokuken.dev/draft-ryzokuken-datetime-extended/documents/rfc-3339.html#name-internet-date-time-format">Date and Time on the Internet: Timestamps with additional information</a>, a draft update to <a href="https://tools.ietf.org/html/rfc3339#appendix-A">RFC 3339</a>.
    </p>
    <p>
      The grammar deviates from the standard given in ISO 8601 in the following ways:
    </p>
    <ul>
      <li>Only the calendar date format is supported, not the weekdate or ordinal date format.</li>
      <li>Two-digit years are disallowed.</li>
      <li><a href="https://tc39.es/ecma262/#sec-expanded-years">Expanded Years</a> of 6 digits are allowed.</li>
      <li>Fractional parts may have 1 through 9 decimal places.</li>
      <li>In time representations, only seconds are allowed to have a fractional part.</li>
      <li>In duration representations, only hours, minutes, and seconds are allowed to have a fractional part.</li>
      <li>The time zone may be given by a suffixed <a href="https://www.iana.org/time-zones">IANA time zone name</a> in square brackets, instead of or in addition to a UTC offset.</li>
      <li>The calendar may be given by a suffixed <a href="https://tools.ietf.org/html/bcp47#section-2.1">BCP 47 key</a> in square brackets.</li>
      <li>A space may be used to separate the date and time in a combined date / time representation, but not in a duration.</li>
      <li>Alphabetic designators may be in lower or upper case.</li>
      <li>Period or comma may be used as the decimal separator.</li>
      <li>A time zone offset of *"-00:00"* is allowed, and means the same thing as *"+00:00"*.</li>
      <li>
        In a combined representation, combinations of date, time, and time zone offset with Basic (no `-` or `:` separators) and Extended (with `-` or `:` separators) formatting are allowed.
        (The date, time, and time zone offset must each be fully in Basic format or Extended format.)
      </li>
      <li>
        When parsing a date representation for a Temporal.PlainMonthDay, the year may be omitted.
        The year may optionally be replaced by *"--"* as in RFC 3339.
      </li>
      <li>When parsing a date representation without a day for a Temporal.PlainYearMonth, the expression is allowed to be in Basic format.</li>
      <li>A duration specifier of *"W"* (weeks) can be combined with any of the other specifiers.</li>
      <li>Anything else described by the standard as requiring mutual agreement between communicating parties, is disallowed.</li>
    </ul>

    <emu-grammar type="definition">
      Alpha : one of
          `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M`
          `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`
          `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m`
          `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z`

      Digit : one of
          `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`

      NonzeroDigit : one of
          `1` `2` `3` `4` `5` `6` `7` `8` `9`

      ASCIISign : one of
          `+` `-`

      Sign :
          ASCIISign
          U+2212

      Hour :
          `0` Digit
          `1` Digit
          `20`
          `21`
          `22`
          `23`

      MinuteSecond :
          `0` Digit
          `1` Digit
          `2` Digit
          `3` Digit
          `4` Digit
          `5` Digit

      DecimalSeparator : one of
          `.` `,`

      DaysDesignator : one of
          `D` `d`

      HoursDesignator : one of
          `H` `h`

      MinutesDesignator : one of
          `M` `m`

      MonthsDesignator : one of
          `M` `m`

      DurationDesignator : one of
          `P` `p`

      SecondsDesignator : one of
          `S` `s`

      DateTimeSeparator :
          &lt;SP&gt;
          `T`
          `t`

      DurationTimeDesignator : one of
          `T` `t`

      WeeksDesignator : one of
          `W` `w`

      YearsDesignator : one of
          `Y` `y`

      UTCDesignator : one of
          `Z` `z`

      Digits :
          Digit Digits?

      DateFourDigitYear :
          Digit Digit Digit Digit

      DateExtendedYear :
          Sign Digit Digit Digit Digit Digit Digit

      DateYear :
          DateFourDigitYear
          DateExtendedYear

      DateMonth :
          `0` NonzeroDigit
          `10`
          `11`
          `12`

      DateDay :
          `0` NonzeroDigit
          `1` Digit
          `2` Digit
          `30`
          `31`

      DateSpecYearMonth :
          DateYear `-`? DateMonth

      DateSpecMonthDay :
          `--`? DateMonth `-`? DateDay

      Date :
          DateYear `-` DateMonth `-` DateDay
          DateYear DateMonth DateDay

      TimeHour :
          Hour

      TimeMinute :
          MinuteSecond

      TimeSecond :
          MinuteSecond
          `60`

      TimeFractionalPart :
          Digit Digit? Digit? Digit? Digit? Digit? Digit? Digit? Digit?

      Fraction :
          DecimalSeparator TimeFractionalPart

      TimeFraction :
          Fraction

      TimeZoneUTCOffsetSign :
          Sign

      TimeZoneUTCOffsetHour :
          Hour

      TimeZoneUTCOffsetMinute :
          MinuteSecond

      TimeZoneUTCOffsetSecond :
          MinuteSecond

      TimeZoneUTCOffsetFraction :
          Fraction

      TimeZoneNumericUTCOffset :
          TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour
          TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour `:` TimeZoneUTCOffsetMinute
          TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute
          TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour `:` TimeZoneUTCOffsetMinute `:` TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction?
          TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction?

      TimeZoneUTCOffset :
          TimeZoneNumericUTCOffset
          UTCDesignator

      TimeZoneUTCOffsetName :
          Sign Hour
          Sign Hour `:` MinuteSecond
          Sign Hour MinuteSecond
          Sign Hour `:` MinuteSecond `:` MinuteSecond Fraction?
          Sign Hour MinuteSecond MinuteSecond Fraction?

      TZLeadingChar :
          Alpha
          `.`
          `_`

      TZChar :
          Alpha
          `.`
          `-`
          `_`

      TimeZoneIANANameComponent :
          TZLeadingChar TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? TZChar? but not one of `.` or `..`

      TimeZoneIANAName :
          TimeZoneIANANameComponent
          TimeZoneIANAName `/` TimeZoneIANANameComponent

      TimeZoneBracketedName :
          TimeZoneIANAName
          `Etc/GMT` ASCIISign Hour
          TimeZoneUTCOffsetName

      TimeZoneBracketedAnnotation :
          `[` TimeZoneBracketedName `]`

      TimeZone :
          TimeZoneUTCOffset
          TimeZoneNumericUTCOffset? TimeZoneBracketedAnnotation

      TimeZoneOffsetRequired :
          UTCDesignator
          TimeZoneNumericUTCOffset TimeZoneBracketedAnnotation?

      CalChar :
          Alpha
          Digit

      CalendarNameComponent :
          CalChar CalChar CalChar CalChar? CalChar? CalChar? CalChar? CalChar?

      CalendarName :
          CalendarNameComponent
          CalendarNameComponent `-` CalendarName

      Calendar :
          `[u-ca=` CalendarName `]`

      TimeSpec :
          TimeHour
          TimeHour `:` TimeMinute
          TimeHour TimeMinute
          TimeHour `:` TimeMinute `:` TimeSecond TimeFraction?
          TimeHour TimeMinute TimeSecond TimeFraction?

      Time :
          TimeSpec TimeZone?

      CalendarDate :
          Date Calendar?

      TimeSpecSeparator :
          DateTimeSeparator TimeSpec

      DateTime :
          Date TimeSpecSeparator? TimeZone?

      CalendarDateTime:
          DateTime Calendar?

      DurationWholeSeconds :
          Digits

      DurationSecondsFraction :
          TimeFraction

      DurationSecondsPart :
          DurationWholeSeconds DurationSecondsFraction? SecondsDesignator

      DurationWholeMinutes :
          Digits

      DurationMinutesFraction :
          TimeFraction

      DurationMinutesPart :
          DurationWholeMinutes DurationMinutesFraction? MinutesDesignator DurationSecondsPart?

      DurationWholeHours :
          Digits

      DurationHoursFraction :
          TimeFraction

      DurationHoursPart :
          DurationWholeHours DurationHoursFraction? HoursDesignator DurationMinutesPart?

      DurationTime :
          DurationTimeDesignator DurationHoursPart
          DurationTimeDesignator DurationMinutesPart
          DurationTimeDesignator DurationSecondsPart

      DurationDays :
          Digits

      DurationDaysPart :
          DurationDays DaysDesignator

      DurationWeeks :
          Digits

      DurationWeeksPart :
          DurationWeeks WeeksDesignator DurationDaysPart?

      DurationMonths :
          Digits

      DurationMonthsPart :
          DurationMonths MonthsDesignator DurationWeeksPart?

      DurationYears :
          Digits

      DurationYearsPart :
          DurationYears YearsDesignator DurationMonthsPart?

      DurationDate :
          DurationYearsPart DurationTime?
          DurationMonthsPart DurationTime?
          DurationWeeksPart DurationTime?
          DurationDaysPart DurationTime?

      Duration :
          Sign? DurationDesignator DurationDate
          Sign? DurationDesignator DurationTime

      TemporalInstantString :
          Date TimeZoneOffsetRequired
          Date DateTimeSeparator TimeSpec TimeZoneOffsetRequired

      TemporalDateString :
          CalendarDateTime

      TemporalDateTimeString :
          CalendarDateTime

      TemporalDurationString :
          Duration

      TemporalMonthDayString :
          DateSpecMonthDay
          DateTime

      TemporalTimeString :
          Time
          DateTime

      TemporalTimeZoneIdentifier :
          TimeZoneNumericUTCOffset
          TimeZoneIANAName

      TemporalTimeZoneString :
          TemporalTimeZoneIdentifier
          TemporalInstantString

      TemporalYearMonthString :
          DateSpecYearMonth
          DateTime

      TemporalZonedDateTimeString :
          Date TimeZoneNumericUTCOffset? TimeZoneBracketedAnnotation Calendar?
          Date DateTimeSeparator TimeSpec TimeZoneNumericUTCOffset? TimeZoneBracketedAnnotation Calendar?

      TemporalCalendarString :
          CalendarName
          TemporalInstantString
          CalendarDateTime
          Time
          DateSpecYearMonth
          DateSpecMonthDay
    </emu-grammar>
  </emu-clause>

  <emu-clause id="sec-temporal-parseisodatetime" aoid="ParseISODateTime">
    <h1>ParseISODateTime ( _isoString_ )</h1>
    <p>
      The ParseISODateTime abstract operation examines any |Time|, |DateTime| or |CalendarDateTime| string accepted by the grammar in <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref> and returns a record with all the date and time components found.
    </p>
    <emu-note>The value of ? ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. Let _year_, _month_, _day_, _hour_, _minute_, _second_, _fraction_, and _calendar_ be the parts of _isoString_ produced respectively by the |DateYear|, |DateMonth|, |DateDay|, |TimeHour|, |TimeMinute|, |TimeSecond|, |TimeFractionalPart|, and |CalendarName| productions, or *undefined* if not present.
      1. Let _year_ be the part of _isoString_ produced by the |DateYear| production.
      1. If the first code unit of _year_ is 0x2212 (MINUS SIGN), replace it with the code unit 0x002D (HYPHEN-MINUS).
      1. Set _year_ to ! ToIntegerOrInfinity(_year_).
      1. If _month_ is *undefined*, then
        1. Set _month_ to 1.
      1. Else,
        1. Set _month_ to ! ToIntegerOrInfinity(_month_).
      1. If _day_ is *undefined*, then
        1. Set _day_ to 1.
      1. Else,
        1. Set _day_ to ! ToIntegerOrInfinity(_day_).
      1. Set _hour_ to ! ToIntegerOrInfinity(_hour_).
      1. Set _minute_ to ! ToIntegerOrInfinity(_minute_).
      1. Set _second_ to ! ToIntegerOrInfinity(_second_).
      1. If _second_ is 60, then
        1. Set _second_ to 59.
      1. If _fraction_ is not *undefined*, then
        1. Set _fraction_ to the string-concatenation of the previous value of _fraction_ and the string *"000000000"*.
        1. Let _millisecond_ be the String value equal to the substring of _fraction_ from 0 to 3.
        1. Set _millisecond_ to ! ToIntegerOrInfinity(_millisecond_).
        1. Let _microsecond_ be the String value equal to the substring of _fraction_ from 3 to 6.
        1. Set _microsecond_ to ! ToIntegerOrInfinity(_microsecond_).
        1. Let _nanosecond_ be the String value equal to the substring of _fraction_ from 6 to 9.
        1. Set _nanosecond_ to ! ToIntegerOrInfinity(_nanosecond_).
      1. Else,
        1. Let _millisecond_ be 0.
        1. Let _microsecond_ be 0.
        1. Let _nanosecond_ be 0.
      1. If ! IsValidISODate(_year_, _month_, _day_) is *false*, throw a *RangeError* exception.
      1. If ! IsValidTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_) is *false*, throw a *RangeError* exception.
      1. Return the new Record {
        [[Year]]: _year_,
        [[Month]]: _month_,
        [[Day]]: _day_,
        [[Hour]]: _hour_,
        [[Minute]]: _minute_,
        [[Second]]: _second_,
        [[Millisecond]]: _millisecond_,
        [[Microsecond]]: _microsecond_,
        [[Nanosecond]]: _nanosecond_,
        [[Calendar]]: _calendar_
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporalinstantstring" aoid="ParseTemporalInstantString">
    <h1>ParseTemporalInstantString ( _isoString_ )</h1>
    <p>
      The ParseTemporalInstantString abstract operation parses an ISO 8601 string and returns the information needed to construct a Temporal.Instant instance.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalInstantString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ! ParseISODateTime(_isoString_).
      1. Let _timeZoneResult_ be ? ParseTemporalTimeZoneString(_isoString_).
      1. Assert: _timeZoneResult_.[[OffsetString]] is not *undefined*.
      1. Return the new Record {
        [[Year]]: _result_.[[Year]],
        [[Month]]: _result_.[[Month]],
        [[Day]]: _result_.[[Day]],
        [[Hour]]: _result_.[[Hour]],
        [[Minute]]: _result_.[[Minute]],
        [[Second]]: _result_.[[Second]],
        [[Millisecond]]: _result_.[[Millisecond]],
        [[Microsecond]]: _result_.[[Microsecond]],
        [[Nanosecond]]: _result_.[[Nanosecond]],
        [[TimeZoneOffsetString]]: _timeZoneResult_.[[OffsetString]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporalzoneddatetimestring" aoid="ParseTemporalZonedDateTimeString">
    <h1>ParseTemporalZonedDateTimeString ( _isoString_ )</h1>
    <p>
      The ParseTemporalZonedDateTimeString abstract operation parses an ISO 8601 string and returns the information needed to construct a Temporal.ZonedDateTime instance.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalZonedDateTimeString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ! ParseISODateTime(_isoString_).
      1. Let _timeZoneResult_ be ? ParseTemporalTimeZoneString(_isoString_).
      1. If _timeZoneResult_.[[Z]] is not *undefined*, then
        1. Throw a *RangeError* exception.
      1. Return the new Record {
        [[Year]]: _result_.[[Year]],
        [[Month]]: _result_.[[Month]],
        [[Day]]: _result_.[[Day]],
        [[Hour]]: _result_.[[Hour]],
        [[Minute]]: _result_.[[Minute]],
        [[Second]]: _result_.[[Second]],
        [[Millisecond]]: _result_.[[Millisecond]],
        [[Microsecond]]: _result_.[[Microsecond]],
        [[Nanosecond]]: _result_.[[Nanosecond]],
        [[TimeZoneOffsetString]]: _timeZoneResult_.[[OffsetString]],
        [[TimeZoneName]]: _timeZoneResult_.[[Name]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporalcalendarstring" aoid="ParseTemporalCalendarString">
    <h1>ParseTemporalCalendarString ( _isoString_ )</h1>
    <p>
      The ParseTemporalCalendarString abstract operation interprets an ISO 8601 string and retrieves the calendar identifier from it.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalCalendarString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _id_ be the part of _isoString_ produced by the |CalendarName| production, or *undefined* if not present.
      1. If _id_ is *undefined*, then
        1. Return *"iso8601"*.
      1. Return _id_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporaldatestring" aoid="ParseTemporalDateString">
    <h1>ParseTemporalDateString ( _isoString_ )</h1>
    <p>
      The ParseTemporalDateString abstract operation parses a full or partial ISO 8601 string and returns the information needed to construct a Temporal.PlainDate instance.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalDateString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ? ParseISODateTime(_isoString_).
      1. Return the new Record {
        [[Year]]: _result_.[[Year]],
        [[Month]]: _result_.[[Month]],
        [[Day]]: _result_.[[Day]],
        [[Calendar]]: _result_.[[Calendar]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporaldatetimestring" aoid="ParseTemporalDateTimeString">
    <h1>ParseTemporalDateTimeString ( _isoString_ )</h1>
    <p>
      The ParseTemporalDateTimeString abstract operation parses an ISO 8601 string and returns the information needed to construct a Temporal.PlainDateTime instance.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalDateTimeString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ? ParseISODateTime(_isoString_).
      1. Return _result_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporaldurationstring" aoid="ParseTemporalDurationString">
    <h1>ParseTemporalDurationString ( _isoString_ )</h1>
    <p>
      The ParseTemporalDurationString abstract operation parses an ISO 8601 string and returns the information needed to construct a Temporal.Duration instance.
    </p>
    <emu-note>The value of ? ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalDurationString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _sign_, _years_, _months_, _weeks_, _days_, _hours_, _fHours_, _minutes_, _fMinutes_, _seconds_, and _fSeconds_ be the parts of _isoString_ produced respectively by the |Sign|, |DurationYears|, |DurationMonths|, |DurationWeeks|, |DurationDays|, |DurationWholeHours|, |DurationHoursFraction|, |DurationWholeMinutes|, |DurationMinutesFraction|, |DurationWholeSeconds|, and |DurationSecondsFraction| productions, or *undefined* if not present.
      1. If _sign_ is the code unit 0x002D (HYPHEN-MINUS) or 0x2212 (MINUS SIGN), then
        1. Let _factor_ be −1.
      1. Else,
        1. Let _factor_ be 1.
      1. Set _years_ to ? ToIntegerOrInfinity(_years_) × _factor_.
      1. Set _months_ to ? ToIntegerOrInfinity(_months_) × _factor_.
      1. Set _weeks_ to ? ToIntegerOrInfinity(_weeks_) × _factor_.
      1. Set _days_ to ? ToIntegerOrInfinity(_days_) × _factor_.
      1. Set _hours_ to ? ToIntegerOrInfinity(_hours_) × _factor_.
      1. Set _minutes_ to ? ToIntegerOrInfinity(_minutes_) × _factor_.
      1. Set _seconds_ to ? ToIntegerOrInfinity(_seconds_) × _factor_.
      1. If _fSeconds_ is not *undefined*, then
        1. Let _fraction_ be the part of _isoString_ produced by the |TimeFractionalPart| production.
        1. Set _fraction_ to the string-concatenation of the previous value of _fraction_ and the string *"000000000"*.
        1. Let _milliseconds_ be the String value equal to the substring of _fraction_ from 0 to 3.
        1. Set _milliseconds_ to ! ToIntegerOrInfinity(_milliseconds_) × _factor_.
        1. Let _microseconds_ be the String value equal to the substring of _fraction_ from 3 to 6.
        1. Set _microseconds_ to ! ToIntegerOrInfinity(_microseconds_) × _factor_.
        1. Let _nanoseconds_ be the String value equal to the substring of _fraction_ from 6 to 9.
        1. Set _nanoseconds_ to ! ToIntegerOrInfinity(_nanoseconds_) × _factor_.
      1. Else,
        1. Let _milliseconds_ be 0.
        1. Let _microseconds_ be 0.
        1. Let _nanoseconds_ be 0.
      1. If _fHours_ is not *undefined*, then
        1. Let _fraction_ be the part of _isoString_ produced by the |TimeFractionalPart| production.
        1. Set _fHours_ to ! ToIntegerOrInfinity(_fraction_) × _factor_ / 10 raised to the power of the length of _fHours_.
      1. Else,
        1. Set _fHours_ to 0.
      1. If _fMinutes_ is not *undefined*, then
        1. Let _fraction_ be the part of _isoString_ produced by the |TimeFractionalPart| production.
        1. Set _fMinutes_ to ! ToIntegerOrInfinity(_fraction_) × _factor_ / 10 raised to the power of the length of _fMinutes_.
      1. Else,
        1. Set _fMinutes_ to 0.
      1. Let _result_ be ? DurationHandleFractions(_fHours_, _minutes_, _fMinutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
      1. Return the new Record {
        [[Years]]: _years_,
        [[Months]]: _months_,
        [[Weeks]]: _weeks_,
        [[Days]]: _days_,
        [[Hours]]: _hours_,
        [[Minutes]]: _result_.[[Minutes]],
        [[Seconds]]: _result_.[[Seconds]],
        [[Milliseconds]]: _result_.[[Milliseconds]],
        [[Microseconds]]: _result_.[[Microseconds]],
        [[Nanoseconds]]: _result_.[[Nanoseconds]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporalmonthdaystring" aoid="ParseTemporalMonthDayString">
    <h1>ParseTemporalMonthDayString ( _isoString_ )</h1>
    <p>
      The ParseTemporalMonthDayString abstract operation parses an ISO 8601 string and returns the information needed to construct a Temporal.PlainMonthDay instance.
    </p>
    <emu-note>The value of ? ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalMonthDayString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _year_, _month_ and _day_ be the parts of _isoString_ produced respectively by the |DateYear|, |DateMonth| and |DateDay| productions, or *undefined* if not present.
      1. If _year_ is not *undefined*, then
        1. Set _year_ to ! ToIntegerOrInfinity(_year_).
      1. If _month_ is *undefined*, then
        1. Set _month_ to 1.
      1. Else,
        1. Set _month_ to ! ToIntegerOrInfinity(_month_).
      1. If _day_ is *undefined*, then
        1. Set _day_ to 1.
      1. Else,
        1. Set _day_ to ! ToIntegerOrInfinity(_day_).
      1. Return the new Record {
        [[Year]]: _year_,
        [[Month]]: _month_,
        [[Day]]: _day_
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporaltimestring" aoid="ParseTemporalTimeString">
    <h1>ParseTemporalTimeString ( _isoString_ )</h1>
    <p>
      The ParseTemporalTimeString abstract operation parses an ISO 8601 string representing a wall-clock time and returns the information needed to construct a Temporal.PlainTime instance.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalTimeString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ? ParseISODateTime(_isoString_).
      1. Return the new Record {
        [[Hour]]: _result_.[[Hour]],
        [[Minute]]: _result_.[[Minute]],
        [[Second]]: _result_.[[Second]],
        [[Millisecond]]: _result_.[[Millisecond]],
        [[Microsecond]]: _result_.[[Microsecond]],
        [[Nanosecond]]: _result_.[[Nanosecond]],
        [[Calendar]]: _result_.[[Calendar]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporaltimezonestring" aoid="ParseTemporalTimeZoneString">
    <h1>ParseTemporalTimeZoneString ( _isoString_ )</h1>
    <p>
      The ParseTemporalTimeZoneString abstract operation interprets an ISO 8601 string and retrieves the information about the time zone from it.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalTimeZoneString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _z_, _sign_, _hours_, _minutes_, _seconds_, _fraction_ and _name_ be the parts of _isoString_ produced respectively by the |UTCDesignator|, |TimeZoneUTCOffsetSign|, |TimeZoneUTCOffsetHour|, |TimeZoneUTCOffsetMinute|, |TimeZoneUTCOffsetSecond|, |TimeZoneUTCOffsetFraction|, and |TimeZoneIANAName| productions, or *undefined* if not present.
      1. If _z_ is not *undefined*, then
        1. Return the new Record: {
          [[Z]]: *"Z"*,
          [[OffsetString]]: *"+00:00"*,
          [[Name]]: *undefined*
          }.
      1. If _hours_ is *undefined*, then
        1. Let _offsetString_ be *undefined*.
      1. Else,
        1. Assert: _sign_ is not *undefined*.
        1. Set _hours_ to ! ToIntegerOrInfinity(_hours_).
        1. If _sign_ is the code unit 0x002D (HYPHEN-MINUS) or the code unit 0x2212 (MINUS SIGN), then
          1. Set _sign_ to −1.
        1. Else,
          1. Set _sign_ to 1.
        1. Set _minutes_ to ! ToIntegerOrInfinity(_minutes_).
        1. Set _seconds_ to ! ToIntegerOrInfinity(_seconds_).
        1. If _fraction_ is not *undefined*, then
          1. Set _fraction_ to the string-concatenation of the previous value of _fraction_ and the string *"000000000"*.
          1. Let _nanoseconds_ be the String value equal to the substring of _fraction_ from 0 to 9.
          1. Set _nanoseconds_ to ! ToIntegerOrInfinity(_nanoseconds_).
        1. Else,
          1. Let _nanoseconds_ be 0.
        1. Let _offsetNanoseconds_ be _sign_ × (((_hours_ × 60 + _minutes_) × 60 + _seconds_) × 10<sup>9</sup> + _nanoseconds_).
        1. Let _offsetString_ be ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
      1. If _name_ is not *undefined*, then
        1. If ! IsValidTimeZoneName(_name_) is *false*, throw a *RangeError* exception.
        1. Set _name_ to ! CanonicalizeTimeZoneName(_name_).
      1. Return the new Record: {
        [[Z]]: *undefined*,
        [[OffsetString]]: _offsetString_,
        [[Name]]: _name_
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-parsetemporalyearmonthstring" aoid="ParseTemporalYearMonthString">
    <h1>ParseTemporalYearMonthString ( _isoString_ )</h1>
    <p>
      The ParseTemporalYearMonthString abstract operation parses a full or partial ISO 8601 string and returns the information needed to construct a Temporal.PlainYearMonth instance.
      It returns a Record with four fields ([[Year]], [[Month]], [[Day]], and [[Calendar]]). [[Calendar]] is a String, and the others are integers.
    </p>
    <emu-alg>
      1. Assert: Type(_isoString_) is String.
      1. If _isoString_ does not satisfy the syntax of a |TemporalYearMonthString| (see <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>), then
        1. Throw a *RangeError* exception.
      1. Let _result_ be ? ParseISODateTime(_isoString_).
      1. Return the new Record {
        [[Year]]: _result_.[[Year]],
        [[Month]]: _result_.[[Month]],
        [[Day]]: _result_.[[Day]],
        [[Calendar]]: _result_.[[Calendar]]
        }.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-topositiveintegerorinfinity" aoid="ToPositiveIntegerOrInfinity">
    <h1>ToPositiveIntegerOrInfinity ( _argument_ )</h1>
    <p>
      The abstract operation ToPositiveIntegerOrInfinity takes argument _argument_. It converts _argument_ to +∞ or an integer _i_ for which <emu-eqn>0 &lt; _i_</emu-eqn>. It performs the following steps:
    </p>
    <emu-alg>
      1. Let _integer_ be ? ToIntegerOrInfinity(_argument_).
      1. If _integer_ is *-∞*<sub>𝔽</sub>, then
        1. Throw a *RangeError* exception.
      1. If _integer_ &le; 0, then
        1. Throw a *RangeError* exception.
      1. Return _integer_.
    </emu-alg>
  </emu-clause>

  <emu-clause id="sec-temporal-preparetemporalfields" aoid="PrepareTemporalFields">
    <h1>PrepareTemporalFields ( _fields_, _fieldNames_, _requiredFields_ )</h1>
    <p>
      The abstract operation PrepareTemporalFields reads the relevant properties of an Object _fields_; ensures all the required properties are present; and creates a new Object with all the properties converted to the correct type.
      The relevant property names are given by the List of Strings _fieldNames_, and the required property names are given by the List of Strings _requiredFields_.
      It performs the following steps:
    </p>
    <emu-note>The value of ? ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
    <emu-alg>
      1. Assert: Type(_fields_) is Object.
      1. Let _result_ be ! OrdinaryObjectCreate(%Object.prototype%).
      1. For each value _property_ of _fieldNames_, do
        1. Let _value_ be ? Get(_fields_, _property_).
        1. If _value_ is *undefined*, then
          1. If _requiredFields_ contains _property_, then
            1. Throw a *TypeError* exception.
          1. If _property_ is in the Property column of <emu-xref href="#table-temporal-field-requirements"></emu-xref>, then
            1. Set _value_ to the corresponding Default value of the same row.
        1. Else,
          1. If _property_ is in the Property column of <emu-xref href="#table-temporal-field-requirements"></emu-xref> and there is a Conversion value in the same row, then
            1. Let _Conversion_ represent the abstract operation named by the Conversion value of the same row.
            1. Set _value_ to ? _Conversion_(_value_).
        1. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_).
      1. Return _result_.
    </emu-alg>
    <emu-table id="table-temporal-field-requirements">
      <emu-caption>Temporal field requirements</emu-caption>
      <table class="real-table">
        <thead>
          <tr>
            <th>Property</th>
            <th>Conversion</th>
            <th>Default</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>*"year"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"month"*</td>
            <td>ToPositiveIntegerOrInfinity</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"monthCode"*</td>
            <td>ToString</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"day"*</td>
            <td>ToPositiveIntegerOrInfinity</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"hour"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"minute"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"second"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"millisecond"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"microsecond"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"nanosecond"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>0</td>
          </tr>
          <tr>
            <td>*"offset"*</td>
            <td>ToString</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"era"*</td>
            <td>ToString</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"eraYear"*</td>
            <td>ToIntegerOrInfinity</td>
            <td>*undefined*</td>
          </tr>
          <tr>
            <td>*"timeZone"*</td>
            <td></td>
            <td>*undefined*</td>
          </tr>
        </tbody>
      </table>
    </emu-table>
  </emu-clause>

  <emu-clause id="sec-temporal-preparepartialtemporalfields" aoid="PreparePartialTemporalFields">
    <h1>PreparePartialTemporalFields ( _fields_, _fieldNames_ )</h1>
    <p>
      The abstract operation PreparePartialTemporalFields reads the relevant properties of an Object _fields_ and creates a new Object with all the properties converted to the correct type.
      The relevant property names are given by the List of Strings _fieldNames_.
      It performs the following steps:
    </p>
    <emu-note>The value of ? ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
    <emu-alg>
      1. Assert: Type(_fields_) is Object.
      1. Let _result_ be ! OrdinaryObjectCreate(%Object.prototype%).
      1. Let _any_ be *false*.
      1. For each value _property_ of _fieldNames_, do
        1. Let _value_ be ? Get(_fields_, _property_).
        1. If _value_ is not *undefined*, then
          1. Set _any_ to *true*.
          1. If _property_ is in the Property column of <emu-xref href="#table-temporal-field-requirements"></emu-xref>, then
            1. Let _Conversion_ represent the abstract operation named by the Conversion value of the same row.
            1. Set _value_ to ? _Conversion_(_value_).
        1. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_).
      1. If _any_ is *false*, then
        1. Throw a *TypeError* exception.
      1. Return _result_.
    </emu-alg>
  </emu-clause>
</emu-clause>
